home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / oleo130s.zip / OLEO130S.TAR / oleo-1.3 / xrdb.c < prev   
C/C++ Source or Header  |  1993-01-10  |  11KB  |  528 lines

  1. #ifdef HAVE_X11_X_H
  2. /* Deal with the X Resource Manager.
  3.    Copyright (C) 1990, 1992, 1993 Free Software Foundation.
  4.  
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. /* Coopted for oleo -t 12/92 */
  20. /* Written by jla, 4/90 */
  21.  
  22. #ifndef alloca
  23. #ifdef __GNUC__
  24. #define alloca __builtin_alloca
  25. #else /* __GNUC__ not defined.  */
  26. #if HAVE_ALLOCA_H
  27. #include <alloca.h>
  28. #else /* not HAVE_ALLOCA_H */
  29. #if defined (MSDOS) && !defined (__TURBOC__)
  30. #include <malloc.h>
  31. #else /* not MSDOS, or __TURBOC__ */
  32. #if defined(_AIX)
  33. #include <malloc.h>
  34. #pragma alloca
  35. #endif /* not _AIX */
  36. #endif /* not MSDOS, or __TURBOC__ */
  37. #endif /* not HAVE_ALLOCA_H */
  38. #endif /* __GNUC__ not defined.  */
  39. #endif /* alloca not defined.  */
  40.  
  41. #include <stdio.h>
  42. #include "sysdef.h"
  43.  
  44. /* This should be included before the X include files; otherwise, we get
  45.    warnings about redefining NULL under BSD 4.3.  */
  46. #include <sys/param.h>
  47. #define NeedFunctionPrototypes 0
  48. #include <X11/X.h>
  49. #include <X11/Xlib.h>
  50. #include <X11/Xutil.h>
  51. #include <X11/Xatom.h>
  52. #include <X11/Xresource.h>
  53. #ifdef VMS
  54. #include "vms-pwd.h"
  55. #else
  56. #include <pwd.h>
  57. #endif
  58. #include <sys/stat.h>
  59.  
  60.  
  61. #if !defined(S_ISDIR) && defined(S_IFDIR)
  62. #define       S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
  63. #endif
  64.  
  65.  
  66. #ifndef MAXPATHLEN
  67. #define MAXPATHLEN    256
  68. #endif
  69.  
  70. extern char *getenv ();
  71. extern struct passwd *getpwuid ();
  72. extern struct passwd *getpwnam ();
  73.  
  74. static char *
  75. gethomedir (dirname)
  76.      char *dirname;
  77. {
  78.   int uid;
  79.   struct passwd *pw;
  80.   char *ptr;
  81.  
  82.   if ((ptr = getenv ("HOME")) == NULL)
  83.     {
  84.       if ((ptr = getenv ("USER")) != NULL)
  85.     pw = getpwnam (ptr);
  86.       else
  87.     {
  88.       uid = getuid ();
  89.       pw = getpwuid (uid);
  90.     }
  91.       if (pw)
  92.     ptr = pw->pw_dir;
  93.       else
  94.     {
  95.       ptr = NULL;
  96.       *dirname = '\0';
  97.     }
  98.     }
  99.  
  100.   if (ptr != NULL) 
  101.     strcpy (dirname, ptr);
  102.  
  103.   dirname += strlen (dirname);
  104.   *dirname = '/';
  105.   dirname++;
  106.   *dirname = '\0';
  107.  
  108.   return dirname;
  109. }
  110.  
  111. static int
  112. file_p (path)
  113.      char *path;
  114. {
  115.   struct stat status;
  116.  
  117.   return (access (path, 4) == 0            /* exists and is readable */
  118.       && stat (path, &status) == 0        /* get the status */
  119.       && !S_ISDIR(status.st_mode));
  120. }
  121.  
  122.  
  123. /* Isn't this just disgusting? */
  124.  
  125. #define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/%L/%T/%N%S:/usr/lib/X11/%l/%T/%N%S:/usr/lib/X11/%T/%N%S"
  126.  
  127. static int
  128. decode_magic (string, file, return_path)
  129.      char *string, *file, *return_path;
  130. {
  131.   char *p = string;
  132.   char *t = return_path;
  133.  
  134.   while (*p)
  135.     {
  136.       if (*p == '%')
  137.     switch (*++p)
  138.       {
  139.       case '%':
  140.         *t++ = '%';
  141.         p++;
  142.         break;
  143.  
  144.       case 'N':
  145.       case 'T':
  146.       case 'S':
  147.       case 'L':
  148.       case 'l':
  149.       case 't':
  150.       case 'c':
  151.       default:
  152.         p++;
  153.         if (*t == '/' && *p == '/')
  154.           p++;
  155.         break;
  156.       }
  157.       else
  158.     *t++ = *p++;
  159.     }
  160.   *t = '\0';
  161.   strcat (return_path, file);
  162.  
  163.   if (file_p (return_path))
  164.     return 1;
  165.  
  166.   return_path[0] = '\0';
  167.   return 0;
  168. }
  169.  
  170. static int
  171. magic_searchpath_decoder (incantation_string, file, return_path)
  172.      char *incantation_string, *return_path, *file;
  173. {
  174.   register char *s = incantation_string;
  175.   register char *p;
  176.  
  177.   /* Must be big enough for "%N%S".  */
  178.   register int string_size = MAXPATHLEN;
  179.   register char *string = (char *) alloca (string_size * sizeof (*string));
  180.  
  181.   while (*s)
  182.     {
  183.       p = s;
  184.  
  185.       while (*p && *p != ':')
  186.     p++;
  187.  
  188.       if (*p == ':' && *(p + 1) == ':')
  189.     {
  190.       /* We know string is big enough for this.  */
  191.       bcopy ("%N%S", string, 5);
  192.       if (decode_magic (string, file, return_path))
  193.         return 1;
  194.  
  195.       s = p + 1;
  196.       continue;
  197.     }
  198.  
  199.       if (p > s)
  200.     {
  201.       int len = p - s;
  202.  
  203.       if (string_size < len+1)
  204.         {
  205.           string_size = 2 * len;
  206.           string = (char *) alloca (string_size * sizeof (*string));
  207.         }
  208.       bcopy (s, string, len);
  209.       string[len + 1] = '\0';
  210.       if (decode_magic (string, file, return_path))
  211.         return 1;
  212.     }
  213.  
  214.       if (p)
  215.     s = p + 1;
  216.       else
  217.     return 0;
  218.     }
  219.  
  220.   return 0;
  221. }
  222.  
  223. static XrmDatabase
  224. get_system_app (class)
  225.      char *class;
  226. {
  227.   XrmDatabase db;
  228.   char path[MAXPATHLEN];
  229.   char *p;
  230.  
  231.   if ((p = getenv ("XFILESEARCHPATH")) == NULL)
  232.     p = X_DEFAULT_SEARCH_PATH;
  233.  
  234.   if (! magic_searchpath_decoder (p, class, path))
  235.     return NULL;
  236.  
  237.   db = XrmGetFileDatabase (path);
  238.   return db;
  239. }
  240.  
  241. static XrmDatabase
  242. get_fallback (display)
  243.      Display *display;
  244. {
  245.   return NULL;
  246. }
  247.  
  248. static XrmDatabase
  249. get_user_app (class)
  250.      char *class;
  251. {
  252.   XrmDatabase db;
  253.   char *magic_path;
  254.   char path[MAXPATHLEN];
  255.  
  256.   if ((magic_path = getenv ("XUSERFILESEARCHPATH")) == NULL)
  257.     {
  258.       char homedir[MAXPATHLEN];
  259.       char *default_magic;
  260.       char *p;
  261.  
  262.       gethomedir (homedir);
  263.  
  264.       if ((p = getenv ("XAPPLRESDIR")) == NULL)
  265.     {
  266.       default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N";
  267.       magic_path = (char *) alloca ((3 * strlen (homedir))
  268.                     + strlen (default_magic));
  269.       sprintf (magic_path, default_magic, homedir, homedir, homedir);
  270.     }
  271.       else
  272.     {
  273.       default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N";
  274.       magic_path = (char *) alloca ((3 * strlen (p))
  275.                     + strlen (default_magic)
  276.                     + strlen (homedir));
  277.       sprintf (magic_path, default_magic, p, p, p, homedir);
  278.     }
  279.     }
  280.  
  281.   if (! magic_searchpath_decoder (magic_path, class, path))
  282.     return NULL;
  283.   
  284.   db = XrmGetFileDatabase (path);
  285.   return db;
  286. }
  287.  
  288. static XrmDatabase
  289. get_user_db (display)
  290.      Display *display;
  291. {
  292.   XrmDatabase db;
  293.   char *xdefs;
  294.  
  295. #ifdef HAVE_X11R4
  296.   xdefs = XResourceManagerString (display);
  297. #else
  298.   xdefs = display->xdefaults;
  299. #endif
  300.  
  301.   if (xdefs != NULL)
  302.     db = XrmGetStringDatabase (xdefs);
  303.   else
  304.     {
  305.       char xdefault[MAXPATHLEN];
  306.  
  307.       gethomedir (xdefault);
  308.       strcat (xdefault, ".Xdefaults");
  309.       db = XrmGetFileDatabase (xdefault);
  310.     }
  311.  
  312.   return db;
  313. }
  314.  
  315. static XrmDatabase
  316. get_environ_db ()
  317. {
  318.   XrmDatabase db;
  319.   char *p;
  320.   char path[MAXPATHLEN];
  321.  
  322.   if ((p = getenv ("XENVIRONMENT")) == NULL)
  323.     {
  324.       gethomedir (path);
  325.       strcat (path, ".Xdefaults-");
  326.       gethostname (path + strlen (path), MAXPATHLEN - strlen (path));
  327.       p = path;
  328.     }
  329.  
  330.   db = XrmGetFileDatabase (p);
  331.   return db;
  332. }
  333.  
  334. /* Types of values that we can find in a database */
  335.  
  336. #define XrmStringType "String"    /* String representation */
  337. XrmRepresentation x_rm_string = 0;    /* Quark representation */
  338.  
  339. /* Load X resources based on the display and a possible -xrm option. */
  340.  
  341. XrmDatabase
  342. x_load_resources (display, xrm_string, myclass)
  343.      Display *display;
  344.      char *xrm_string, *myclass;
  345. {
  346.   XrmDatabase rdb;
  347.   XrmDatabase db;
  348.  
  349.   if (!x_rm_string)
  350.     x_rm_string = XrmStringToQuark (XrmStringType);
  351.  
  352.   XrmInitialize ();
  353.   rdb = XrmGetStringDatabase ("");
  354.  
  355.   /* Get application system defaults */
  356.   db = get_system_app (myclass);
  357.   if (db != NULL)
  358.     XrmMergeDatabases (db, &rdb);
  359.  
  360.   /* Get Fallback resources */
  361.   db = get_fallback (display);
  362.   if (db != NULL)
  363.     XrmMergeDatabases (db, &rdb);
  364.  
  365.   /* Get application user defaults */
  366.   db = get_user_app (myclass);
  367.   if (db != NULL)
  368.     XrmMergeDatabases (db, &rdb);
  369.  
  370.   /* get User defaults */
  371.   db = get_user_db (display);
  372.   if (db != NULL)
  373.     XrmMergeDatabases (db, &rdb);
  374.  
  375.   /* Get Environment defaults. */
  376.   db = get_environ_db ();
  377.   if (db != NULL)
  378.     XrmMergeDatabases (db, &rdb);
  379.   
  380.   /* Last, merge in any specification from the command line. */
  381.   if (xrm_string != NULL)
  382.     {
  383.       db = XrmGetStringDatabase (xrm_string);
  384.       if (db != NULL)
  385.     XrmMergeDatabases (db, &rdb);
  386.     }
  387.  
  388.   return rdb;
  389. }
  390.  
  391. /* Retrieve the value of the resource specified by NAME with class CLASS
  392.    and of type TYPE from database RDB.  The value is returned in RET_VALUE. */
  393.  
  394. int
  395. x_get_resource (rdb, name, class, expected_type, ret_value)
  396.      XrmDatabase rdb;
  397.      char *name, *class;
  398.      XrmRepresentation expected_type;
  399.      XrmValue *ret_value;
  400. {
  401.   XrmValue value;
  402.   XrmName namelist[100];
  403.   XrmClass classlist[100];
  404.   XrmRepresentation type;
  405.  
  406.   XrmStringToNameList(name, namelist);
  407.   XrmStringToClassList(class, classlist);
  408.  
  409.   if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True
  410.       && (type == expected_type))
  411.     {
  412.       if (type == x_rm_string)
  413.     ret_value->addr = (char *) value.addr;
  414.       else
  415.     bcopy (value.addr, ret_value->addr, ret_value->size);
  416.  
  417.       return value.size;
  418.     }
  419.  
  420.   return 0;
  421. }
  422.  
  423. /* Retrieve the string resource specified by NAME with CLASS from
  424.    database RDB. */
  425.  
  426. char *
  427. x_get_string_resource (rdb, name, class)
  428.      XrmDatabase rdb;
  429.      char *name, *class;
  430. {
  431.   XrmValue value;
  432.  
  433.   if (!x_rm_string)
  434.     x_rm_string = XrmStringToQuark (XrmStringType);
  435.  
  436.   if (x_get_resource (rdb, name, class, x_rm_string, &value))
  437.     return (char *) value.addr;
  438.  
  439.   return (char *) 0;
  440. }
  441.  
  442. #ifdef TESTRM
  443. #include <stdio.h>
  444. #include "arg-list.h"
  445.  
  446. static void
  447. fatal (msg, prog, x1, x2, x3, x4, x5)
  448.     char *msg, *prog;
  449.     int x1, x2, x3, x4, x5;
  450. {
  451.     extern int errno;
  452.  
  453.     if (errno)
  454.       perror (prog);
  455.  
  456.     (void) fprintf (stderr, msg, prog, x1, x2, x3, x4, x5);
  457.     exit (1);
  458. }
  459.  
  460. main (argc, argv)
  461.     int argc;
  462.     char **argv;
  463. {
  464.   Display *display;
  465.   char *displayname, *resource_string, *class;
  466.   XrmDatabase xdb;
  467.   List *arg_list, *lp;
  468.  
  469.   arg_list = arg_listify (argc, argv);
  470.  
  471.   lp = member ("-d", arg_list);
  472.   if (!NIL (lp))
  473.     displayname = car (cdr (lp));
  474.   else
  475.     displayname = "localhost:0.0";
  476.  
  477.   lp = member ("-xrm", arg_list);
  478.   if (! NIL (lp))
  479.     resource_string = car (cdr (lp));
  480.   else
  481.     resource_string = (char *) 0;
  482.  
  483.   lp = member ("-c", arg_list);
  484.   if (! NIL (lp))
  485.     class = car (cdr (lp));
  486.   else
  487.     class = "Emacs";
  488.  
  489.   free_arglist (arg_list);
  490.  
  491.  
  492.  
  493.   if (!(display = XOpenDisplay (displayname)))
  494.     fatal ("Can't open display '%s'\n", XDisplayName (displayname));
  495.  
  496.   xdb = x_load_resources (display, resource_string, class);
  497.  
  498. #if 0
  499.   /* In a real program, you'd want to also do this: */
  500.   display->db = xdb;
  501. #endif
  502.  
  503.   while (1)
  504.     {
  505.       char line[90];
  506.  
  507.       printf ("String: ");
  508.       gets (line);
  509.       if (strlen (line))
  510.     {
  511.       char *value = x_get_string_resource (xdb, line, class);
  512.  
  513.       if (value != NULL)
  514.         printf ("\t%s:  %s\n\n", line, value);
  515.       else
  516.         printf ("\tNo Value.\n\n");
  517.     }
  518.       else
  519.     break;
  520.     }
  521.   printf ("\tExit.\n\n");
  522.  
  523.   XCloseDisplay (display);
  524. }
  525. #endif /* TESTRM */
  526. #endif /* HAVE_X11_X_H */
  527.  
  528.